package com.dykj.fireFighting.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.dykj.fireFighting.api.base.emergency.entity.EmergencyStaff;
import com.dykj.fireFighting.api.base.emergency.service.IEmergencyStaffService;
import com.dykj.fireFighting.api.base.news.service.IAliMessageService;
import com.dykj.fireFighting.common.starter.redisson.service.RedisService;
import com.dykj.fireFighting.web.model.Device;
import com.dykj.fireFighting.web.model.sixin.DevHisSXin;
import com.dykj.fireFighting.web.model.vo.SocialUnitVo;
import com.dykj.fireFighting.web.rocketmq.message.SXinPushMessage;
import com.dykj.fireFighting.web.rocketmq.producer.InsertDevHisSXinProducer;
import com.dykj.fireFighting.web.rocketmq.producer.SXinPushProducer;
import com.dykj.fireFighting.web.service.DevHisSXinService;
import com.dykj.fireFighting.web.service.DevHisService;
import com.dykj.fireFighting.web.service.SysUserService;
import com.dykj.fireFighting.web.utils.UUIDUtils;
import net.sf.json.JSONObject;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.quickserver.util.data.dataProcessing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DevHisSXinServiceImpl implements DevHisSXinService {
    @Autowired
    private RedisService redisService;
    @Autowired
    private DevHisService devHisService;
    @Autowired
    private InsertDevHisSXinProducer insertDevHisSXinProducer;
    @Autowired
    private SXinPushProducer sXinPushProducer;
    @Autowired
    private SysUserService sysUserService;
    @DubboReference
    private IAliMessageService aliMessageService;
    @DubboReference
    private IEmergencyStaffService iEmergencyStaffService;

    @Override
    public void putDevHisSXinToMQ(Object obj) {
        JSONObject jsonMsg = new JSONObject().fromObject(obj);
        //1.查询设备，有设备继续，无设备return
        String devId= jsonMsg.getString("imei");
        Device device = JSON.parseObject((String) redisService.get(devId), Device.class);
        if (device == null) {
            device = devHisService.queryCreateBy(devId);
        }
        if (device == null) {
            return;
        }
        redisService.set(devId, JSON.toJSONString(device));

        String type = jsonMsg.getString("type");
        if (2 == Integer.parseInt(type)){
            return;
        }

        //2.解析获取List<DevHisSXin>
        String value = jsonMsg.getString("value");
        if (!value.startsWith("4040")){
            return;
        }
        List<DevHisSXin> devHisSXinList = getDevHisSXin(value,device);
        if (devHisSXinList.size() == 0) {
            return;
        }
        //3.循环遍历list，判断是否报警、入库、推送
        for (DevHisSXin devHisSXin : devHisSXinList) {
            //推送开关
            boolean pushSwitch = true;
            //报警次数
            int alarmNum = 0;
            Object object = redisService.get(device.getRelationId() + "_alarmNum");
            if (object != null) {
                alarmNum = (int) object;
            }
            //获取推送人信息
            SocialUnitVo socialUnitVo = getContacts(device);
            devHisSXin.setUnitId(device.getUnitId());
            devHisSXin.setUnitName(device.getUnitName());
            devHisSXin.setCenterUnitId(socialUnitVo.getCenterUnitId());
            //当type为状态帧===并且状态码为200 正常，不推送不入库，删除报警次数
            if (2 == devHisSXin.getType() && devHisSXin.getPartStatusNum().equals("200")) {
                redisService.del(device.getRelationId() + "_alarmNum");
                return;
            }
            //当type为状态帧===并且状态码为不为200 告警状态，推送、入库、电话
            if (2 == devHisSXin.getType() && !devHisSXin.getPartStatusNum().equals("200")){
                if (alarmNum > device.getAlarmNumber()){
                    pushSwitch = false;
                }
            }
            //当type为模拟量帧，不推送
            if (3 == devHisSXin.getType()) {
                pushSwitch = false;
            }
            //4.发送消息给MQ
            if (pushSwitch) {
                //发送短信
                List<EmergencyStaff> emergencyStaffList;
                emergencyStaffList = getWaterEgencyStaffList(device.getUnitId());
                aliMessageService.sendAliMessageBatch(emergencyStaffList, "唐山臻旭科技有限公司", "SMS_213772600", device.getName(), devHisSXin.getStateTime(),devHisSXin.getPartStatus());
                redisService.set(device.getRelationId() + "_alarmNum", alarmNum + 1);
                //推送消息
                SXinPushMessage sXinPushMessage = new SXinPushMessage();
                device.setStatus(devHisSXin.getPartStatus());
                sXinPushMessage.setDeviceName(device.getName());
                sXinPushMessage.setDevice(device);
                sXinPushMessage.setAlarmTime(devHisSXin.getStateTime());
                sXinPushMessage.setDevHisId(devHisSXin.getId());
                sXinPushMessage.setUnit(socialUnitVo);
                sXinPushProducer.asyncSend(sXinPushMessage, new SendCallback(){
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.println("=======发送四信推送消息成功=======");
                    }
                    @Override
                    public void onException(Throwable throwable) {
                        System.out.println("=======发送四信推送消息失败=======");
                    }
                });
            }
            //入数据库
            insertDevHisSXinProducer.asyncSend(devHisSXin,new SendCallback(){
                @Override
                public void onSuccess(SendResult sendResult) {
                    System.out.println("=======发送插入四信历史记录消息成功=======");
                }
                @Override
                public void onException(Throwable throwable) {
                    System.out.println("=======发送插入四信历史记录消息失败=======");
                }
            });
        }
    }

    private List<DevHisSXin> getDevHisSXin(String str,Device device) {
        List<DevHisSXin> devList = new ArrayList<>();

        String[] strs = dataProcessing.strToStrs(str);
        //信息条数
        int num = dataProcessing.hexStringToInt10(strs[28]);
        System.out.println("信息对象数目：" + num);

        //解析时间
        String[] time = new String[]{strs[6], strs[7], strs[8], strs[9], strs[10], strs[11]};
        String stateTime = dataProcessing.strsToTime(time);
        System.out.println("时间标签：" + stateTime);

        //类型标志
        int type = dataProcessing.hexStringToInt10(strs[27]);
        System.out.println("类型标志：" + type);

        //状态帧
        if (2 == type) {
            //信息对象数目  跳46
            for (int i = 0; i < num; i++) {
                int j = i * 46;
                DevHisSXin devHisSXin = new DevHisSXin();
                devHisSXin.setId(UUIDUtils.getTimeUUID());
                devHisSXin.setRelationId(device.getRelationId());
                devHisSXin.setDeviceName(device.getName());
                devHisSXin.setStateTime(stateTime);
                devHisSXin.setType(type);

                //系统类型标志
                int sysType = dataProcessing.hexStringToInt10(strs[29 + j]);
                String sysTypeStr = getSysTypeStr(sysType);
                System.out.println("系统类型标志" + i + "：" + sysType + "=====" + sysTypeStr);
                devHisSXin.setSysType(sysType);
                devHisSXin.setSysTypeStr(sysTypeStr);

                //部件类型
                int partType = dataProcessing.hexStringToInt10(strs[31 + j]);
                String partTypeStr = getPartTypeStr(partType);
                System.out.println("部件类型" + i + "：" + partType + "=====" + partTypeStr);
                devHisSXin.setPartType(partType);
                devHisSXin.setPartTypeStr(partTypeStr);

                //部件地址
                System.out.println("部件地址" + i + "：" + strs[32 + j] + " " + strs[33 + j] + " " + strs[34 + j] + " " + strs[35 + j]);

                //部件状态
                Map<String,String> map = getPartStatus(strs[37 + j],strs[36 + j] );
                String partStatus = map.get("partStatus");
                String partStatusNum = map.get("partStatusNum");
                System.out.println("部件状态" + i + "：" + partStatus);
                System.out.println("部件状态" + i + "：" + strs[36 + j] + " " + strs[37 + j]);
                devHisSXin.setPartStatus(partStatus);
                devHisSXin.setPartStatusNum(partStatusNum);
                devList.add(devHisSXin);
            }
        }
        //模拟量帧
        if (3 == type) {
            //信息对象数目  跳16
            for (int i = 0; i < num; i++) {
                int j = i * 16;
                DevHisSXin devHisSXin = new DevHisSXin();
                devHisSXin.setId(UUIDUtils.getTimeUUID());
                devHisSXin.setRelationId(device.getRelationId());
                devHisSXin.setDeviceName(device.getName());
                devHisSXin.setStateTime(stateTime);
                devHisSXin.setType(type);

                //系统类型标志
                int sysType = dataProcessing.hexStringToInt10(strs[29 + j]);
                String sysTypeStr = getSysTypeStr(sysType);
                System.out.println("系统类型标志" + i + "：" + sysType + "=====" + sysTypeStr);
                devHisSXin.setSysType(sysType);
                devHisSXin.setSysTypeStr(sysTypeStr);

                //部件类型
                int partType = dataProcessing.hexStringToInt10(strs[31 + j]);
                String partTypeStr = getPartTypeStr(partType);
                System.out.println("部件类型" + i + "：" + partType + "=====" + partTypeStr);
                devHisSXin.setPartType(partType);
                devHisSXin.setPartTypeStr(partTypeStr);

                //部件地址
                System.out.println("部件地址" + i + "：" + strs[32 + j] + " " + strs[33 + j] + " " + strs[34 + j] + " " + strs[35 + j]);

                //模拟量类型
                int moniType = dataProcessing.hexStringToInt10(strs[36 + j]);
                String moniTypeStr = getMoniTypeStr(moniType);
                System.out.println("模拟量类型" + i + "：" + moniType+ "=====" + moniTypeStr);
                devHisSXin.setMoniType(moniType);
                devHisSXin.setMoniTypeStr(moniTypeStr);

                //模拟量值
                int i1 = dataProcessing.sumHexStringToInt10(strs[37 + j], strs[38 + j]);
//                int i2 = dataProcessing.sumHexStringToInt10GD(strs[37 + j], strs[38 + j]);
                System.out.println(i1);
                System.out.println("模拟量值" + i + "：" + strs[37 + j] + strs[38 + j]);
                devHisSXin.setMoniValue(i1);
                devList.add(devHisSXin);
            }
        }
        return devList;
    }

    private Map<String, String> getPartStatus(String stra, String strb) {
        int[] d = dataProcessing.henTo2(stra);
        int[] g = dataProcessing.henTo2(strb);
        int strLen1 = d.length;
        int strLen2 = g.length;
        d = Arrays.copyOf(d, strLen1 + strLen2);
        System.arraycopy(g, 0, d, strLen1, strLen2);
        d = reverse(d,d.length);
        System.out.println("打印状态码："+Arrays.toString(d));
        StringJoiner sb = new StringJoiner(",");
        StringJoiner sbNum = new StringJoiner(",");
        if (1==d[0]){
            sb.add("低于下限值告警");
            sbNum.add("101");
        }
        if (1 == d[1]) {
            sb.add("高于上限值告警");
            sbNum.add("102");
        }
        if (1 == d[7]){
            sb.add("电量告警");
            sbNum.add("103");
        }
        if (sb.length()==0){
            sb.add("正常");
            sbNum.add("200");
        }
        Map<String, String> map = new HashMap<>();
        map.put("partStatusNum",sbNum.toString());
        map.put("partStatus",sb.toString());
        return map;
    }

    private String getMoniTypeStr(int a) {
        String moniTypeStr = "";
        switch (a) {
            case 5:
                moniTypeStr = "压力";
                break;
            case 128:
                moniTypeStr = "信号强度";
                break;
            case 129:
                moniTypeStr = "电量";
                break;
            case 154:
                moniTypeStr = "液位";
                break;
            case 136:
                moniTypeStr = "电池电压";
                break;
            default:
                moniTypeStr = "未解析状态";
        }
        return moniTypeStr;
    }

    private String getSysTypeStr(int a){
        if (131 == a) {
            return "消防管道压力系统";
        }
        if (132 == a) {
            return "消防水池液位系统";
        }
        if (133 == a) {
            return "市政消防栓监测系统";
        }
        if (134 == a) {
            return "消防水箱液位系统";
        }
        return "未解析状态";
    }
    private String getPartTypeStr(int a){
        if (128 == a) {
            return "消防水压";
        }
        if (129 == a) {
            return "消防液位";
        }
        if (130 == a) {
            return "消防栓智能闷盖";
        }
        return "未解析状态";
    }

    private List<EmergencyStaff> getWaterEgencyStaffList(String unitId) {
        return iEmergencyStaffService.getWaterStaffByUnitid(unitId);
    }

    private SocialUnitVo getContacts(Device device) {
        SocialUnitVo unit = JSON.parseObject((String) redisService.get(device.getRelationId() + "-unit"), SocialUnitVo.class);
        if (null == unit) {
            unit = new SocialUnitVo();
            Map<String, Object> centerUnit = sysUserService.getCenterUnit(device.getUnitId());
//            unit.setUnitId(device.getUnitId());
//            unit.setUnitName(device.getUnitName());
            unit.setCenterUnitId(centerUnit.get("id").toString());
//            unit.setCenterUnitName(centerUnit.get("name").toString());
            unit.setUnitUserIds(sysUserService.getUserByUnitId(device.getUnitId()));
            unit.setCenterUserIds(sysUserService.getCenterUserByUnitId(device.getUnitId()));

            List<String> idList = sysUserService.getUnitIds(device.getUnitId());
            List<String> centerIds = unit.getCenterUserIds();
            List<String> unitIds = new ArrayList<>();
            for (String centerid : centerIds) {
                for (String unitid : idList){
                    unitIds.add(centerid+"-"+unitid);
                }
            }
            unit.setUnitIds(unitIds);

            redisService.set(device.getRelationId() + "-unit", JSON.toJSONString(unit));
        }
        return unit;
    }
    public int[] reverse(int a[], int n)
    {
        int[] b = new int[n];
        int j = n;
        for (int i = 0; i < n; i++) {
            b[j - 1] = a[i];
            j = j - 1;
        }
        return b;
    }
}
